from django.shortcuts import render, redirect
from QQLoginTool.QQtool import OAuthQQ
from django.views import View
from django import http
from django.conf import settings
from django.contrib.auth import login
import re
from django_redis import get_redis_connection

from meiduo_mall.utils.response_code import RETCODE
from .models import OAuthQQUser
import logging
from users.models import User
from .utils import generate_openid_sign, check_openid
from carts.utils import merge_cart_cookie_to_redis
logger = logging.getLogger('django')

class QQAuthURLView(View):
    """拼接QQ登录url"""
    def get(self, request):

        # 1.获取查询参数next
        next = request.GET.get('next') or '/'
        # 创建QQLoginTool SDK中的OAuthQQ对象
        # auth_qq = OAuthQQ(client_id='appid', client_secret='app_key', redirect_uri='qq登录成功的回调url', state='next')
        auth_qq = OAuthQQ(client_id=settings.QQ_CLIENT_ID,
                          client_secret=settings.QQ_CLIENT_SECRET,
                          redirect_uri=settings.QQ_REDIRECT_URI,
                          state=next)
        # 使用QQLoginTool 调用它里面的get_qq_url方法拼接好QQ登录url
        login_url = auth_qq.get_qq_url()
        # 响应json
        return http.JsonResponse({'login_url': login_url, 'code': RETCODE.OK, 'errmsg': 'OK'})


class QQAuthView(View):
    """QQ登录成功回调处理"""
    def get(self, request):
        # 1. 获取查询参数中code
        code = request.GET.get('code')
        if code is None:
            return http.HttpResponseForbidden('缺少code')
        # 2. 创建QQ 登录工具对象
        auth_qq = OAuthQQ(client_id=settings.QQ_CLIENT_ID,
                          client_secret=settings.QQ_CLIENT_SECRET,
                          redirect_uri=settings.QQ_REDIRECT_URI)
        try:
            # 3. 调用QQ工具对象中get_access_token方法用code获取access_token
            access_token = auth_qq.get_access_token(code)
            # 4. get_open_id方法用access_token 获取openid
            openid = auth_qq.get_open_id(access_token)
        except Exception as e:
            logger.error(e)
            return http.HttpResponseServerError('QQ认证失败')
        # 查询openid在存储过,如果存储过,说明openid已绑定过用户,直接登录
        try:
            oauth_model = OAuthQQUser.objects.get(openid=openid)
            # 如果查询到openid,说明openid已绑定过用户
            # 获取当前openid绑定的user
            user = oauth_model.user
            # 状态保持
            login(request, user)
            # 重定向
            response = redirect(request.GET.get('state') or '/')
            response.set_cookie('username', user.username, max_age=settings.SESSION_COOKIE_AGE)
            merge_cart_cookie_to_redis(request, response)
            return response
        except OAuthQQUser.DoesNotExist:
            # 对openid进行加密之后再渲染
            openid = generate_openid_sign(openid)
            context = {'openid': openid}
            # 如果openid没有绑定用户,渲染一个绑定界面
            return render(request, 'oauth_callback.html', context)

    def post(self, request):
        # 1.接收表单数据
        query_dict = request.POST
        mobile = query_dict.get('mobile')
        password = query_dict.get('password')
        sms_code = query_dict.get('sms_code')
        openid = query_dict.get('openid')
        # 2.校验
        # dict1 = query_dict.dict()
        # dict1.pop('openid')
        # dict1.values()
        if all([mobile, password, sms_code, openid]) is False:
            return http.HttpResponseForbidden('缺少必传参数')
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.HttpResponseForbidden('请求正确手机号')
        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            return http.HttpResponseForbidden('请求8-20位密码')
        redis_conn = get_redis_connection('verify_code')
        sms_code_server = redis_conn.get('sms_%s' % mobile)
        if sms_code_server is None:
            return render(request, 'oauth_callback.html', {'sms_code_errmsg': '短信验证码已过期'})
        redis_conn.delete('sms_%s' % mobile)
        if sms_code != sms_code_server.decode():
            return render(request, 'oauth_callback.html', {'sms_code_errmsg': '短信验填写错误'})

        # 对openid进行解密,用原始openid和user进行绑定
        openid = check_openid(openid)
        if openid is None:
            return render(request, 'oauth_callback.html', {'openid_errmsg': 'QQ绑定失败'})

        try:
            # 校验手机号是美多老用户,还是新用户
            user = User.objects.get(mobile=mobile)
            # 校验用户密码是否正确
            if user.check_password(password) is False:
                return render(request, 'oauth_callback.html', {'qq_login_errmsg': 'QQ绑定失败'})
        except User.DoesNotExist:
            # 创建一个新user
            user = User.objects.create_user(username=mobile, password=password, mobile=mobile)


        # 3.openid绑定user
        OAuthQQUser.objects.create(
            user=user,
            openid=openid
        )
        # 4. 状态保持
        login(request, user)
        # 5. 创建响应
        response = redirect(request.GET.get('state') or '/')
        # 6. cookie存储username
        response.set_cookie('username', user.username, max_age=settings.SESSION_COOKIE_AGE)
        merge_cart_cookie_to_redis(request, response)
        # 7.响应
        return response
